package dao

import (
	"fmt"
	"strings"
	"time"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/models/cashlog"
	"yundian/internel/app/models/users"
	"yundian/internel/app/models/withdrawalsetting"
	"yundian/internel/pkg/dbs"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

type CashDao struct{}

func NewCashDao() *CashDao {
	return &CashDao{}
}

func (dao *CashDao) GetServiceOrderCashList(param *request.GetOrdersCashListReq) *dingo.ErrorWrap {

	var (
		lst    []*request.GetOrdersCashListRes
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	fields := `col.id,user_id,money,transfer_money,service_charge,type,col.status,verify_status,unit_name,order_type, 
	bank_name,bank_accounts,payee_url,message, u.name, DATE_FORMAT(verify_time,'%Y-%m-%d %T') verify_time, 
	DATE_FORMAT(create_time,'%Y-%m-%d %T')create_time,DATE_FORMAT(update_time,'%Y-%m-%d %T')update_time`
	db := global.Orm.Table("cash_order_log col").Select(fields)
	db.Joins("left join users u on u.id = col.user_id")

	if param.IsAdmin != helper.TypeNumIsAdminOperator {
		db.Where("col.user_id=?", param.LoginUserId)
	}

	if param.UserId > 0 {
		db.Where("col.user_id=?", param.UserId)
	}
	if param.Type > 0 {
		db.Where("col.type=?", param.Type)
	}
	if param.OrderType > 0 {
		db.Where("col.order_type=?", param.OrderType)
	}
	if param.VerifyStatus > 0 {
		db.Where("col.verify_status=?", param.VerifyStatus)
	}

	db.Order("col.id DESC")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

// 服务订单提现审核
func (dao *CashDao) VerifyServiceOrder(param *request.OrdersCashReq) *dingo.ErrorWrap {
	updateMap := map[string]interface{}{
		"status":        helper.TypeNumCashOrderLogStatusReview,
		"verify_status": param.Db.VerifyStatus,
		"verify_time":   time.Now().Format("2006-01-02 15:04:05"),
	}
	if param.Db.VerifyStatus == helper.TypeNumCashOrderLogVerifyStatusPass {
		updateMap["status"] = helper.TypeNumCashOrderLogStatusDone
	}

	//db := global.Orm.Model(&param.Db).Where("id=?", param.Db.Id)

	sql := `UPDATE cash_order_log SET status=?,verify_status=?,service_charge=?,message=?,
	transfer_money=money-money*?/100,verify_time=? WHERE id=? AND verify_status=?`
	db := global.Orm.Exec(sql, updateMap["status"], updateMap["verify_status"], param.Db.ServiceCharge, param.Db.Message,
		param.Db.ServiceCharge, updateMap["verify_time"], param.Db.Id, helper.TypeNumCashOrderLogVerifyStatusReview)
	return dingo.ErrorIf(db.Error)
}

// 服务订单提现申请
func (dao *CashDao) ApplyServiceOrder(param *request.OrdersCashReq) *dingo.ErrorWrap {
	var cashCount int64
	statusIn := []int{helper.TypeNumCashOrderLogVerifyStatusReview}

	tx, key := dbs.GormBegin("ApplyServiceOrder")
	db := tx.Model(&param.Db).Where("user_id=? AND verify_status IN ? AND order_type=?", param.UserId, statusIn, param.Db.OrderType).Count(&cashCount)
	if db.Error != nil || cashCount > 0 {
		dbs.GormRollback(tx, key, db.Error)
		return dingo.ErrorIf(db.Error, utils.AddStrJudge(cashCount == 0, "exist"))
	}

	// 可提现金额校验
	userInfo := NewUserDao().GetUserInfoById(param.UserId).Unwrap().(*users.UserModel)
	cashNum := NewCashDao().GetOrderCashNum(param).Unwrap().(int64)
	if param.Db.OrderType == helper.TypeNumCashOrderLogOrderTypeRoom {
		param.Db.ServiceCharge = userInfo.TaxRateRoom
		roomData := NewRoomDaoDao().GetRoomOrdersToCashByUserId(param).Unwrap().(*request.OrdersCashRes)
		if roomData.Cash-cashNum <= 0 {
			dbs.GormRollback(tx, key, db.Error)
			return dingo.ErrorIf(db.Error, "money")
		}
	}
	if param.Db.OrderType == helper.TypeNumCashOrderLogOrderTypeGoods {
		param.Db.ServiceCharge = userInfo.TaxRateGoods
		goodsData := NewGoodsDao().GetGoodsOrdersToCashByUserId(param).Unwrap().(*request.OrdersCashRes)
		if goodsData.Cash-cashNum <= 0 {
			dbs.GormRollback(tx, key, db.Error)
			return dingo.ErrorIf(db.Error, "money")
		}
	}
	if param.Db.OrderType == helper.TypeNumCashOrderLogOrderTypeAutomate {
		param.Db.ServiceCharge = userInfo.TaxRateAutomate
		goodsData := NewAutomateDaoDao().GetAutomateOrdersToCashByUserId(param).Unwrap().(*request.OrdersCashRes)
		if goodsData.Cash-cashNum <= 0 {
			dbs.GormRollback(tx, key, db.Error)
			return dingo.ErrorIf(db.Error, "money")
		}
	}

	param.Db.UserId = param.UserId
	param.Db.Status = helper.TypeNumCashOrderLogStatusReview
	param.Db.VerifyStatus = helper.TypeNumCashOrderLogVerifyStatusReview
	//param.Db.TransferMoney -= int(utils.ToDiv(param.Db.Money*param.Db.ServiceCharge, 100))
	if db = tx.Create(&param.Db); db.Error != nil {
		dbs.GormRollback(tx, key, db.Error)
		return dingo.ErrorIf(db.Error, "")
	}

	dbs.GormCommit(tx, key)
	return dingo.ErrorIf(db.Error, "")
}

// 查询己提现金额
func (dao *CashDao) GetOrderCashNum(param *request.OrdersCashReq) *dingo.ErrorWrap {
	var money int64

	db := global.Orm.Debug().Table("cash_order_log").Select("IFNULL(SUM(money),0)money")
	db.Where("user_id=? AND verify_status IN (1,3) AND order_type=?", param.UserId, param.Db.OrderType).Find(&money)

	return dingo.ErrorIf(db.Error, money)
}

func (dao *CashDao) GetCashList(param *request.CashListReq) *dingo.ErrorWrap {

	var (
		lst    []*cashlog.UserWithdrawalLog
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Debug().Table("cash_log w").
		Select("w.*,u.phone,u.name,u.wx_income_qrcode").
		Joins("left join users u on u.id = w.user_id")

	if param.UserId != 2 {
		db.Where("w.user_id=?", param.UserId)
	}
	if param.Name != "" {
		db.Where("u.name like ?", fmt.Sprint("%", param.Name, "%"))
	} // 申请人姓名
	if param.Phone != "" {
		db.Where("u.phone = ?", param.Phone)
	} // 手机号码
	if param.Status > 0 {
		db.Where("w.state = ?", param.Status)
	}

	// 时间查询
	if param.BeginTime != "" {
		beginTime := strings.Split(param.BeginTime, ",")
		db.Where("w.create_at >= ? and w.create_at<= ?", beginTime[0], beginTime[1])
	}

	// 排序
	if param.SortField != "" && param.SortOrder == "ascend" {
		db.Order(fmt.Sprintf("w.%s asc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField != "" && param.SortOrder == "descend" {
		db.Order(fmt.Sprintf("w.%s desc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField == "" {
		db.Order("w.create_at desc")
	}

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

func (dao *CashDao) InsertCashLog(m *cashlog.CashLogModel) *dingo.ErrorWrap {

	db := global.Orm.Debug().Table("cash_log").Create(&m)
	return dingo.ErrorIf(db.Error, true)
}

func (dao *CashDao) InsertTxCashLog(m *cashlog.CashLogModel) *dingo.ErrorWrap {

	db := global.Orm.Begin().Table("cash_log").Create(&m)
	if db.Error != nil {
		db.Rollback()
	}
	db.Commit()
	return dingo.ErrorIf(db.Error, true)
}

func (dao *CashDao) InsertTransferOrder(tm *cashlog.TransferOrder) *dingo.ErrorWrap {

	db := global.Orm.Table("transfer_order").Create(tm)
	return dingo.ErrorIf(db.Error, true)
}

func (dao *CashDao) InsertTransferOrderPcl(tm *cashlog.TransferOrderPcl) *dingo.ErrorWrap {

	db := global.Orm.Table("transfer_order_pcl").Create(tm)
	return dingo.ErrorIf(db.Error, true)
}

func (dao *CashDao) UpdateCashLog(id int, updateVal map[string]interface{}) *dingo.ErrorWrap {
	db := global.Orm.Table("cash_log").Where("id = ?", id).Updates(&updateVal)
	return dingo.ErrorIf(db.Error, true)
}

func (dao *CashDao) GetQrCodeCashList(param *request.CashListReq) *dingo.ErrorWrap {

	var (
		lst    []*cashlog.UserWithdrawalLog
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Debug().Table("cash_log w").
		Select("w.*,u.phone,u.name,u.wx_income_qrcode,p_user.name as parent_name , p_user.user_name as parent_user_name,u.parent_id,u.user_name, u.tax_rate").
		Joins("left join users u on u.id = w.user_id").
		Joins("left join users p_user on p_user.id = u.parent_id")

	// 非运营商 用户限制
	if param.IsAdmin != helper.TypeNumIsAdminOperator && param.IsAdmin != helper.TypeNumIsAdminStaff {
		db.Where("w.user_id=?", param.UserId)
	}

	if param.Name != "" {
		db.Where("u.name like ?", fmt.Sprint("%", param.Name, "%"))
	}

	if param.Phone != "" {
		db.Where("u.phone = ?", param.Phone)
	}

	if param.Status > 0 {
		db.Where("w.state = ?", param.Status)
	}

	//if param.UserId > 0 {
	//	db.Where("w.user_id = ?", param.UserId)
	//}

	//商户
	//if param.IsAdmin == 3 && param.IsPlace == 1 {
	//	db.Where("u.is_admin = 3 and u.is_place = 1")
	//}

	//代理商
	if param.IsAdmin > 4 {

		db.Where("u.is_admin = ?", param.IsAdmin)
	}

	// 时间查询
	if param.BeginTime != "" {
		beginTime := strings.Split(param.BeginTime, ",")
		db.Where("w.create_at >= ? and w.create_at<= ?", beginTime[0], beginTime[1])
	}

	// 排序
	if param.SortField != "" && param.SortOrder == "ascend" {
		db.Order(fmt.Sprintf("w.%s asc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField != "" && param.SortOrder == "descend" {
		db.Order(fmt.Sprintf("w.%s desc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField == "" {
		db.Order("w.create_at desc")
	}
	db.Group("w.id")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

func (dao *CashDao) GetWithdrawalSettingInfo(isType uint8) *dingo.ErrorWrap {
	m := withdrawalsetting.WithdrawalSetting{}
	db := global.Orm.Table("withdrawal_setting").Where("type = ?", isType).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

//查询是否提现过
//查询网点是否登录
func (dao *CashDao) GetUserIsCash(userId int) *dingo.ErrorWrap {
	var loginCount int64
	db := global.Orm.Table("cash_log").Where("user_id = ?", userId).Count(&loginCount)
	return dingo.ErrorIf(db.Error, loginCount)
}

//查询提现大于两千的用户
func (dao *CashDao) GetCashUser() *dingo.ErrorWrap {
	var lst []*cashlog.UserWithdrawalLog
	db := global.Orm.Table("cash_log cl").Joins("left join users u on cl.user_id = u.id").Where("cl.money>=2000").Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}
